Skip to content

Conversation

sergio-eliot-rodriguez
Copy link
Collaborator

@sergio-eliot-rodriguez sergio-eliot-rodriguez commented Oct 16, 2025

Implemented TicketSauce components expressed by user specified in #18366 (which this PR resolves), namely actions
List of Events
Event Details
Orders
Order Details
Ticket Checkin IDs
and source
New Event
which was specified by the app developer via email.

Summary by CodeRabbit

  • New Features
    • Ticketsauce: actions to list/get events, orders, ticket check‑in IDs, and fetch event/order details; a "New Event" source that polls and emits events with sample emit and dynamic UI fields for selecting events/orders; client helpers for API calls.
    • Airweave: full app integration with collection/source management, search, sync, SDK-backed client methods and README.
    • New apps: CoinAPI, Copicake, Cronly, Topdesk.
  • Bug Fixes / Maintenance
    • Microsoft Teams: minor version bumps.
  • Chores
    • Component version and package manifest updates; added runtime dependencies.
  • Tests
    • Added test event fixture for source testing.

Copy link

vercel bot commented Oct 16, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Preview Comments Updated (UTC)
pipedream-docs-redirect-do-not-edit Ignored Ignored Oct 21, 2025 9:40pm

@pipedream-component-development
Copy link
Collaborator

Thank you so much for submitting this! We've added it to our backlog to review, and our team has been notified.

@pipedream-component-development
Copy link
Collaborator

Thanks for submitting this PR! When we review PRs, we follow the Pipedream component guidelines. If you're not familiar, here's a quick checklist:

Copy link
Contributor

coderabbitai bot commented Oct 16, 2025

Walkthrough

Adds multiple new integrations and actions: Ticketsauce (app client methods, actions, polling "New Event" source, fixtures, package bump), Airweave (app client methods, many actions, README, package bump), several new simple app descriptors (coinapi, copicake, cronly, topdesk), and Microsoft Teams version bumps and a message endpoint path fix.

Changes

Cohort / File(s) Summary
Ticketsauce — App, Actions & Source
components/ticketsauce/ticketsauce.app.mjs, components/ticketsauce/package.json, components/ticketsauce/actions/.../*.mjs, components/ticketsauce/sources/new-event/*, components/ticketsauce/actions/get-events/get-events.mjs, components/ticketsauce/actions/get-event-details/get-event-details.mjs, components/ticketsauce/actions/get-orders/get-orders.mjs, components/ticketsauce/actions/get-order-details/get-order-details.mjs, components/ticketsauce/actions/get-ticket-checkin-ids/get-ticket-checkin-ids.mjs
Added Ticketsauce app methods and propDefinitions (_makeRequest, listEvents, getEventDetails, listOrders, getOrderDetails, getTicketCheckinIds, async eventId/orderId options), new action modules that map props to API params and call the app methods, a polling source new-event with persistence/sample fixture, and bumped package version + dependencies.
Airweave — App, Actions & README
components/airweave/airweave.app.mjs, components/airweave/actions/*/*.mjs, components/airweave/README.md, components/airweave/package.json
Expanded Airweave propDefinitions and client/auth helpers (_apiKey, _baseUrl, _client), many API wrapper methods (collections, sourceConnections, sources), multiple new actions (create/get/list/delete collections, list sources, search collection, trigger sync), README added, and package version + dependencies updated.
Microsoft Teams — Minor fixes & version bumps
components/microsoft_teams/microsoft_teams.app.mjs, components/microsoft_teams/actions/*/*.mjs, components/microsoft_teams/sources/*/*.mjs, components/microsoft_teams/package.json
Bumped several action/source versions and updated listChannelMessages to use the non-delta messages endpoint (/messages), plus package version bump.
New simple app descriptors
components/coinapi/coinapi.app.mjs, components/copicake/copicake.app.mjs, components/cronly/cronly.app.mjs, components/topdesk/topdesk.app.mjs
Added simple app modules exporting default app objects with type, app, empty propDefinitions, and an authKeys() helper method.
New package manifests
components/coinapi/package.json, components/copicake/package.json, components/cronly/package.json, components/topdesk/package.json
Added package.json files for new component packages (metadata, version, publishConfig).

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant Action as "Ticketsauce Action"
    participant App as "Ticketsauce App"
    participant API as "Ticketsauce API"

    Note right of Action: action.run({ $ })
    Action->>App: call listEvents/getEventDetails/listOrders/getOrderDetails/getTicketCheckinIds($, { ... })
    App->>API: HTTP GET (via _makeRequest / axios)
    API-->>App: JSON response
    App-->>Action: return response
Loading
sequenceDiagram
    autonumber
    participant Source as "Ticketsauce New Event Source"
    participant DB as "DB (persistence)"
    participant App as "Ticketsauce App"
    participant Emit as "Emitter"

    Source->>DB: _getLastCreated()
    DB-->>Source: lastCreated
    Source->>App: listEvents(params)
    App-->>Source: events[]
    Source->>Source: filter by created_after, sort asc, apply maxResults
    Source->>DB: _setLastCreated(newLastCreated) when new events
    loop for each new event
        Source->>Emit: $emit(event, meta)
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

🐇 I hop through endpoints, sniff and find,
New actions fetch, new sources bind.
I stash the times, emit with glee,
Clients, README, packages — all set free.
— a happy rabbit, bouncing with tea 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description Check ⚠️ Warning The PR description does not follow the required template structure. The repository template specifies a "## WHY" section that should be completed by the author, but the provided description lacks this section header and does not follow the template format. While the description does provide relevant information about what was implemented and references the resolved issue (#18366), it fails to adhere to the expected template structure and does not explicitly explain the rationale for these changes. Update the PR description to follow the required template format by adding a "## WHY" section that explains the rationale for implementing these Ticketsauce components. The section should articulate why these specific actions and the source were needed and how they fulfill the requirements specified in issue #18366. This will help reviewers understand the context and purpose of these changes beyond just the list of what was implemented.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The PR title "new ticketsauce actions and source" is directly related to the main changes in the changeset. The pull request adds five new Ticketsauce actions (get-events, get-event-details, get-orders, get-order-details, get-ticket-checkin-ids) and one new source (new-event), along with supporting infrastructure updates. The title accurately summarizes the primary purpose and is clear and concise enough for a reviewer scanning the history to understand the changeset's intent.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 37abd15 and 4304a3c.

📒 Files selected for processing (8)
  • components/coinapi/coinapi.app.mjs (1 hunks)
  • components/coinapi/package.json (1 hunks)
  • components/copicake/copicake.app.mjs (1 hunks)
  • components/copicake/package.json (1 hunks)
  • components/cronly/cronly.app.mjs (1 hunks)
  • components/cronly/package.json (1 hunks)
  • components/topdesk/package.json (1 hunks)
  • components/topdesk/topdesk.app.mjs (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • components/copicake/package.json
🚧 Files skipped from review as they are similar to previous changes (6)
  • components/coinapi/coinapi.app.mjs
  • components/coinapi/package.json
  • components/topdesk/package.json
  • components/cronly/package.json
  • components/cronly/cronly.app.mjs
  • components/copicake/copicake.app.mjs
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-01-29T22:59:38.825Z
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#15436
File: components/printful/printful.app.mjs:55-63
Timestamp: 2025-01-29T22:59:38.825Z
Learning: Console.log statements should be removed before merging PRs to maintain code quality and prevent potential security risks from exposing sensitive information in logs.

Applied to files:

  • components/topdesk/topdesk.app.mjs
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Verify TypeScript components
  • GitHub Check: Publish TypeScript components
  • GitHub Check: Lint Code Base
  • GitHub Check: pnpm publish

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
components/ticketsauce/sources/new-event/new-event.mjs (1)

79-88: Simplify the lastCreated update logic.

The current implementation searches through all events to find the most recent created date, but since newEvents contains only events created after lastCreated, the most recent event in newEvents already represents the new maximum.

Apply this diff to simplify:

       // Update last created date if we have new events
       if (newEvents.length > 0) {
-        // Find the most recent created date
-        const mostRecentEvent = events.reduce((latest, current) => 
-          Date.parse(current.Event.created) > Date.parse(latest.Event.created) 
-            ? current 
-            : latest
-        );
+        // Get the most recent event from newEvents (last in sorted array)
+        const mostRecentEvent = newEvents[newEvents.length - 1];
         this._setLastCreated(mostRecentEvent.Event.created);
       }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fe7f45d and 04e8c2a.

📒 Files selected for processing (9)
  • components/ticketsauce/actions/get-event-details/get-event-details.mjs (1 hunks)
  • components/ticketsauce/actions/get-events/get-events.mjs (1 hunks)
  • components/ticketsauce/actions/get-order-details/get-order-details.mjs (1 hunks)
  • components/ticketsauce/actions/get-orders/get-orders.mjs (1 hunks)
  • components/ticketsauce/actions/get-ticket-checkin-ids/get-ticket-checkin-ids.mjs (1 hunks)
  • components/ticketsauce/package.json (2 hunks)
  • components/ticketsauce/sources/new-event/new-event.mjs (1 hunks)
  • components/ticketsauce/sources/new-event/test-event.mjs (1 hunks)
  • components/ticketsauce/ticketsauce.app.mjs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (6)
components/ticketsauce/actions/get-ticket-checkin-ids/get-ticket-checkin-ids.mjs (2)
components/ticketsauce/actions/get-events/get-events.mjs (1)
  • params (83-98)
components/ticketsauce/actions/get-orders/get-orders.mjs (1)
  • params (131-147)
components/ticketsauce/sources/new-event/new-event.mjs (1)
components/ticketsauce/ticketsauce.app.mjs (1)
  • events (12-15)
components/ticketsauce/actions/get-events/get-events.mjs (2)
components/ticketsauce/actions/get-event-details/get-event-details.mjs (1)
  • params (53-56)
components/ticketsauce/actions/get-orders/get-orders.mjs (1)
  • params (131-147)
components/ticketsauce/actions/get-event-details/get-event-details.mjs (1)
components/ticketsauce/actions/get-events/get-events.mjs (1)
  • params (83-98)
components/ticketsauce/actions/get-orders/get-orders.mjs (3)
components/ticketsauce/actions/get-event-details/get-event-details.mjs (1)
  • params (53-56)
components/ticketsauce/actions/get-events/get-events.mjs (1)
  • params (83-98)
components/ticketsauce/actions/get-ticket-checkin-ids/get-ticket-checkin-ids.mjs (1)
  • params (48-51)
components/ticketsauce/ticketsauce.app.mjs (5)
components/ticketsauce/sources/new-event/new-event.mjs (1)
  • events (50-58)
components/ticketsauce/actions/get-event-details/get-event-details.mjs (1)
  • params (53-56)
components/ticketsauce/actions/get-events/get-events.mjs (1)
  • params (83-98)
components/ticketsauce/actions/get-orders/get-orders.mjs (1)
  • params (131-147)
components/ticketsauce/actions/get-ticket-checkin-ids/get-ticket-checkin-ids.mjs (1)
  • params (48-51)
🪛 GitHub Actions: Components Checks
components/ticketsauce/package.json

[error] 1-1: pnpm install failed due to frozen-lockfile. The lockfile is not up to date with package.json. Run 'pnpm install' without --frozen-lockfile or update the lockfile. Specifiers in the lockfile ({}) don't match specs in package.json ({"@pipedream/platform":"^3.1.0"}).

🪛 GitHub Actions: Pull Request Checks
components/ticketsauce/package.json

[error] 1-1: pnpm install failed due to frozen-lockfile: pnpm-lock.yaml is not up to date with package.json. Specifiers in the lockfile don't match specs in package.json ("@pipedream/platform":"^3.1.0"). Run 'pnpm install --no-frozen-lockfile' or update the lockfile.


[error] 1-1: Dependency specifier mismatch detected in lockfile vs package.json for @pipedream/platform (^3.1.0).

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: pnpm publish
🔇 Additional comments (3)
components/ticketsauce/actions/get-order-details/get-order-details.mjs (1)

1-48: LGTM!

The action structure is well-organized with appropriate propDefinitions for dynamic option loading, and the implementation correctly retrieves order details.

components/ticketsauce/sources/new-event/test-event.mjs (1)

1-47: LGTM!

The test fixture provides appropriate sample data for the New Event source.

components/ticketsauce/sources/new-event/new-event.mjs (1)

1-105: Verify whether the Ticketsauce /events endpoint supports or requires pagination.

The concern is valid: listEvents is called without pagination parameters in new-event.mjs, get-events.mjs, and propDefinitions, while other API calls in the same integration (e.g., listOrders) explicitly use per_page and page. If the /events endpoint returns paginated results, only the first page will be fetched, causing events beyond the first page to be missed.

However, this appears to be a consistent pattern across the integration, suggesting either the endpoint returns all results by default or there's a shared gap. Consult the Ticketsauce API documentation or test the endpoint to confirm whether pagination is needed. If required, add pagination parameters (e.g., per_page and pagination loop logic) to the listEvents calls.

Regarding deduplication: the dedupe: "unique" strategy combined with event id and lastCreated tracking should correctly prevent duplicates across runs, assuming event IDs are unique.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (7)
components/ticketsauce/actions/get-ticket-checkin-ids/get-ticket-checkin-ids.mjs (2)

38-50: Use integer props + bounds for pagination params; avoid sending strings.

Define perPage/page as integer with min/max, and send numbers to the API.

@@
-    perPage: {
-      type: "string",
+    perPage: {
+      type: "integer",
       label: "Per Page",
       description: "How many results to retrieve (per page). Max 5000.",
       optional: true,
+      default: 100,
+      min: 1,
+      max: 5000,
     },
@@
-    page: {
-      type: "string",
+    page: {
+      type: "integer",
       label: "Page",
       description: "Which page to return. For example, if per_page is 20, and page is 3, the results would show 41-60.",
       optional: true,
-      default: "1",
+      default: 1,
+      min: 1,
     },
@@
-    const params = {
-      per_page: this.perPage,
-      page: this.page,
-    };
+    const params = {
+      per_page: this.perPage,
+      page: this.page,
+    };

Also applies to: 52-56


52-61: Optionally add “paginate all” support to meet the pagination guideline.

Add a boolean paginateAll to fetch all pages in one run; otherwise keep current single-page behavior. As per component checklist.

@@
   props: {
@@
+    paginateAll: {
+      type: "boolean",
+      label: "Paginate All",
+      description: "If true, fetches all pages of check-in IDs.",
+      optional: true,
+      default: false,
+    },
@@
   async run() {
-    const params = {
+    const params = {
       per_page: this.perPage,
       page: this.page,
     };
 
-    return this.ticketsauce.getTicketCheckinIds({
-      eventId: this.eventId,
-      params,
-    });
+    if (!this.paginateAll) {
+      return this.ticketsauce.getTicketCheckinIds({ eventId: this.eventId, params });
+    }
+    const all = [];
+    let page = params.page || 1;
+    while (true) {
+      const res = await this.ticketsauce.getTicketCheckinIds({ eventId: this.eventId, params: { ...params, page } });
+      const items = Array.isArray(res) ? res : (res?.data ?? []);
+      all.push(...items);
+      if (!items.length || (params.per_page && items.length < params.per_page)) break;
+      page += 1;
+    }
+    return all;
   },

Please confirm Ticketsauce’s “Ticket Check-in IDs” endpoint supports per_page/page and whether 5000 is the documented max. If different, we’ll adjust min/max and loop stop conditions.

components/ticketsauce/actions/get-events/get-events.mjs (2)

59-69: Set explicit defaults to match the descriptions.

Descriptions say default sort is date/asc, but props have no defaults. Add them for consistency.

   sortBy: {
     type: "string",
     label: "Sort By",
     description: "Which field to sort by. By default ('date'), will sort events by their start date. Other options are 'name' (event name) or 'city' (the city where the event is located).",
     optional: true,
+    default: "date",
     options: [
       "date",
       "name",
       "city",
     ],
   },
@@
   sortDir: {
     type: "string",
     label: "Sort Direction",
     description: "Which direction you'd like to sort - either ascending ('asc' - the default) or descending ('desc').",
     optional: true,
+    default: "asc",
     options: [
       "asc",
       "desc",
     ],
   },

Also applies to: 70-79


87-103: Avoid sending undefined query keys.

Clean the params object before calling the app method to prevent undefined from being sent.

   async run() {
-    const params = {
+    const paramsRaw = {
       partner_id: this.partnerId,
       organization_id: this.organizationId,
       start_after: this.startAfter,
       end_before: this.endBefore,
       active_only: this.activeOnly,
       privacy_type: this.privacyType,
       sort_by: this.sortBy,
       sort_dir: this.sortDir,
       include_performers: this.includePerformers,
     };
-
-    return this.ticketsauce.listEvents({
-      params,
-    });
+    const params = Object.fromEntries(Object.entries(paramsRaw).filter(([, v]) => v !== undefined));
+    return this.ticketsauce.listEvents({ params });
   },
components/ticketsauce/actions/get-orders/get-orders.mjs (3)

38-51: Use integer props + bounds for perPage/page.

Ensure numeric types and enforce API limits (max 500 as described).

   perPage: {
-      type: "string",
+      type: "integer",
       label: "Per Page",
       description: "How many results to retrieve (per page). Max 500.",
       optional: true,
-      default: "100",
+      default: 100,
+      min: 1,
+      max: 500,
     },
   page: {
-      type: "string",
+      type: "integer",
       label: "Page",
       description: "Which page to return. For example, if per_page is 20, and page is 3, the results would show 41-60.",
       optional: true,
-      default: "1",
+      default: 1,
+      min: 1,
     },

136-156: Strip undefined query params before request.

Prevents sending dead/undefined keys; keeps requests clean.

-    const params = {
+    const paramsRaw = {
       per_page: this.perPage,
       page: this.page,
       q: this.q,
       return_questionnaires: this.returnQuestionnaires,
       return_tickets: this.returnTickets,
       return_line_item_fees: this.returnLineItemFees,
       ordered_after: this.orderedAfter,
       ordered_before: this.orderedBefore,
       modified_after: this.modifiedAfter,
       modified_before: this.modifiedBefore,
       sort_by: this.sortBy,
       sort_dir: this.sortDir,
       total_above: this.totalAbove,
       total_below: this.totalBelow,
     };
+    const params = Object.fromEntries(Object.entries(paramsRaw).filter(([, v]) => v !== undefined));
 
     return this.ticketsauce.listOrders({
       eventId: this.eventId,
       params,
     });

38-75: Optional: add paginateAll to fetch all pages in one action.

Meets the “handle pagination” checklist; keeps current behavior default.

@@
   props: {
@@
+    paginateAll: {
+      type: "boolean",
+      label: "Paginate All",
+      description: "If true, fetches all pages of orders.",
+      optional: true,
+      default: false,
+    },
@@
   async run() {
-    const paramsRaw = {
+    const paramsRaw = {
       per_page: this.perPage,
       page: this.page,
@@
-    const params = Object.fromEntries(Object.entries(paramsRaw).filter(([, v]) => v !== undefined));
-
-    return this.ticketsauce.listOrders({
-      eventId: this.eventId,
-      params,
-    });
+    const params = Object.fromEntries(Object.entries(paramsRaw).filter(([, v]) => v !== undefined));
+    if (!this.paginateAll) {
+      return this.ticketsauce.listOrders({ eventId: this.eventId, params });
+    }
+    const all = [];
+    let page = params.page || 1;
+    while (true) {
+      const res = await this.ticketsauce.listOrders({ eventId: this.eventId, params: { ...params, page } });
+      const items = Array.isArray(res) ? res : (res?.data ?? []);
+      all.push(...items);
+      if (!items.length || (params.per_page && items.length < params.per_page)) break;
+      page += 1;
+    }
+    return all;
   },

Confirm Ticketsauce’s “Orders” endpoint page size limit (doc says 500 here). If different, update max.

Also applies to: 100-121, 135-157

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 04e8c2a and 94760df.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (5)
  • components/ticketsauce/actions/get-event-details/get-event-details.mjs (1 hunks)
  • components/ticketsauce/actions/get-events/get-events.mjs (1 hunks)
  • components/ticketsauce/actions/get-order-details/get-order-details.mjs (1 hunks)
  • components/ticketsauce/actions/get-orders/get-orders.mjs (1 hunks)
  • components/ticketsauce/actions/get-ticket-checkin-ids/get-ticket-checkin-ids.mjs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • components/ticketsauce/actions/get-order-details/get-order-details.mjs
  • components/ticketsauce/actions/get-event-details/get-event-details.mjs
🧰 Additional context used
🧬 Code graph analysis (3)
components/ticketsauce/actions/get-ticket-checkin-ids/get-ticket-checkin-ids.mjs (2)
components/ticketsauce/actions/get-events/get-events.mjs (1)
  • params (88-98)
components/ticketsauce/actions/get-orders/get-orders.mjs (1)
  • params (136-151)
components/ticketsauce/actions/get-events/get-events.mjs (3)
components/ticketsauce/actions/get-event-details/get-event-details.mjs (1)
  • params (58-61)
components/ticketsauce/actions/get-orders/get-orders.mjs (1)
  • params (136-151)
components/ticketsauce/actions/get-ticket-checkin-ids/get-ticket-checkin-ids.mjs (1)
  • params (53-56)
components/ticketsauce/actions/get-orders/get-orders.mjs (3)
components/ticketsauce/actions/get-event-details/get-event-details.mjs (1)
  • params (58-61)
components/ticketsauce/actions/get-events/get-events.mjs (1)
  • params (88-98)
components/ticketsauce/actions/get-ticket-checkin-ids/get-ticket-checkin-ids.mjs (1)
  • params (53-56)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: pnpm publish
  • GitHub Check: Verify TypeScript components
  • GitHub Check: Publish TypeScript components
  • GitHub Check: Lint Code Base
🔇 Additional comments (1)
components/ticketsauce/actions/get-events/get-events.mjs (1)

14-27: Confirm whether the Events API supports pagination; add props if so.

If the endpoint accepts per_page/page, expose them (integer with min/max) and forward to params to align with the pagination checklist. If not, ignore.

Also applies to: 87-98

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
components/ticketsauce/sources/new-event/new-event.mjs (1)

78-84: Consider clarifying the cursor update logic.

The logic correctly updates lastCreated to the most recent event from the full events array (not just newEvents), which properly advances the cursor. However, the condition if (newEvents.length > 0) might be clearer as a comment explaining that we only update the cursor when we've emitted new events.

Consider adding a clarifying comment:

-      // Update last created date if we have new events
       if (newEvents.length > 0) {
+        // Update cursor to the most recent event from all fetched events
         // Find the most recent created date
         const mostRecentEvent = events.reduce((latest, current) =>
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 94760df and 46e2542.

📒 Files selected for processing (3)
  • components/ticketsauce/package.json (2 hunks)
  • components/ticketsauce/sources/new-event/new-event.mjs (1 hunks)
  • components/ticketsauce/ticketsauce.app.mjs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
components/ticketsauce/sources/new-event/new-event.mjs (1)
components/ticketsauce/ticketsauce.app.mjs (1)
  • events (14-17)
components/ticketsauce/ticketsauce.app.mjs (5)
components/ticketsauce/sources/new-event/new-event.mjs (1)
  • events (50-58)
components/ticketsauce/actions/get-event-details/get-event-details.mjs (1)
  • params (58-61)
components/ticketsauce/actions/get-events/get-events.mjs (1)
  • params (88-98)
components/ticketsauce/actions/get-ticket-checkin-ids/get-ticket-checkin-ids.mjs (1)
  • params (53-56)
components/ticketsauce/actions/get-orders/get-orders.mjs (1)
  • params (136-151)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Publish TypeScript components
  • GitHub Check: Verify TypeScript components
  • GitHub Check: Lint Code Base
  • GitHub Check: pnpm publish
🔇 Additional comments (7)
components/ticketsauce/package.json (1)

1-18: LGTM!

The version bump and dependency addition are appropriate for the new components being introduced. The past lockfile issue has been addressed.

components/ticketsauce/sources/new-event/new-event.mjs (3)

4-32: LGTM!

The source metadata, props, and timer configuration are well-structured. The 1-hour interval appropriately matches the API cache behavior mentioned in the comment.


34-46: LGTM!

The cursor management and metadata generation helpers follow standard patterns and integrate well with the db service.


93-100: LGTM!

The deploy hook with a 25-event limit and the unlimited run method follow the standard polling source pattern.

components/ticketsauce/ticketsauce.app.mjs (3)

31-71: LGTM!

The orderId propDefinition correctly implements pagination with context tracking and appropriate handling of empty results. The label format provides helpful order identification.


74-85: LGTM!

The _makeRequest helper follows the standard pattern for API integration, properly handling authentication and parameter merging.


86-134: LGTM!

The API helper methods are well-structured and correctly delegate to _makeRequest. Each method appropriately handles its parameters and constructs the correct API paths.

Comment on lines 7 to 30
eventId: {
type: "string",
label: "Event",
description: "Select an event",
async options({
partnerId, organizationId,
}) {
const events = await this.listEvents({
partnerId,
organizationId,
});

if (!events?.length) {
return [];
}

const options = events.map((eventData) => ({
label: `${eventData.Event.name} - ${eventData.Event.city} (${eventData.Event.start})`,
value: eventData.Event.id,
}));

return options;
},
},
Copy link
Contributor

@coderabbitai coderabbitai bot Oct 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Implement pagination for event options.

The eventId propDefinition fetches all events without pagination, which could fail to load all available events if the dataset is large. Per the component guidelines: "Handle pagination for API requests to ensure all data/events are processed."

Apply a similar pagination pattern to the orderId propDefinition (lines 31-71):

       async options({
-        partnerId, organizationId,
+        partnerId, organizationId, prevContext,
       }) {
         const events = await this.listEvents({
           partnerId,
           organizationId,
+          params: {
+            per_page: 100,
+            page: prevContext?.page || 0,
+          },
         });
 
         if (!events?.length) {
-          return [];
+          return prevContext?.page > 0
+            ? {
+              options: [],
+              context: {},
+            }
+            : [];
         }
 
         const options = events.map((eventData) => ({
           label: `${eventData.Event.name} - ${eventData.Event.city} (${eventData.Event.start})`,
           value: eventData.Event.id,
         }));
 
-        return options;
+        return {
+          options,
+          context: {
+            page: (prevContext?.page || 0) + 1,
+          },
+        };
       },

Note: Verify that the Ticketsauce API supports per_page and page parameters for the /events endpoint.


🏁 Script executed:

#!/bin/bash
# Verify if the Ticketsauce API documentation mentions pagination parameters for the events endpoint

rg -i "per_page|page|pagination" --type md -C 3

Length of output: 191188


🏁 Script executed:

#!/bin/bash
# Examine the ticketsauce component to verify pagination implementation

# First, find the ticketsauce component file
find . -name "ticketsauce.app.mjs" -o -name "ticketsauce*.mjs" | head -20

Length of output: 44


🏁 Script executed:

#!/bin/bash
# Get the ticketsauce component content to verify pagination claims
cat components/ticketsauce/ticketsauce.app.mjs | head -150

Length of output: 3029


🏁 Script executed:

#!/bin/bash
# Check if there's API documentation or examples for ticketsauce
find components/ticketsauce -type f \( -name "*.md" -o -name "*.js" -o -name "*.mjs" \) | head -20

Length of output: 490


🏁 Script executed:

#!/bin/bash
# Look for any common API integration files to understand pagination patterns
rg -l "per_page|prevContext" --type mjs components/ | head -10

Length of output: 27


🏁 Script executed:

#!/bin/bash
# Search for the listEvents method specifically in ticketsauce
rg -A 20 "listEvents\s*\(" components/ticketsauce/

Length of output: 4957


🏁 Script executed:

#!/bin/bash
# Search for orderId propDefinition in ticketsauce to compare implementation
rg -A 30 "orderId.*propDefinition\|orderId\s*:\s*\{" components/ticketsauce/

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Check the complete file structure
wc -l components/ticketsauce/ticketsauce.app.mjs && head -200 components/ticketsauce/ticketsauce.app.mjs

Length of output: 3076


🏁 Script executed:

#!/bin/bash
# Look for any Ticketsauce-specific documentation or README
find components/ticketsauce -name "README*" -o -name "*.md" | xargs cat 2>/dev/null || echo "No README found"

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Search for pagination patterns in the codebase to see if prevContext is the standard
rg -B 5 -A 15 'prevContext.*page' components/ --type mjs | head -80

Length of output: 27


🏁 Script executed:

#!/bin/bash
# Specifically check orderId implementation in ticketsauce
ast-grep --pattern 'orderId.*:.*{
  $$$
  async options($_) {
    $$$
  }
  $$$
}'

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Get the full ticketsauce.app.mjs to understand the complete context
cat components/ticketsauce/ticketsauce.app.mjs

Length of output: 3029


🏁 Script executed:

#!/bin/bash
# Search for API method to understand pagination support
rg -B 5 -A 20 "_makeRequest|getEventDetails|listEvents" components/ticketsauce/ticketsauce.app.mjs | head -100

Length of output: 2031


🏁 Script executed:

#!/bin/bash
# Check GitHub or external documentation reference
rg -i "ticketsauce.*api|api.*ticketsauce" components/ticketsauce/ --type md

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Look at the prop definitions more carefully
rg -B 2 -A 50 "propDefinitions\s*=" components/ticketsauce/ticketsauce.app.mjs | head -150

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Final check: examine lines 7-30 and 31-71 as mentioned in review
sed -n '1,150p' components/ticketsauce/ticketsauce.app.mjs

Length of output: 3029


🏁 Script executed:

#!/bin/bash
# Check if orderId even exists and how pagination is implemented there
grep -n "orderId" components/ticketsauce/ticketsauce.app.mjs | head -20

Length of output: 101


🏁 Script executed:

#!/bin/bash
# Look for the entire propDefinitions section
sed -n '/propDefinitions/,/^  [a-zA-Z]/p' components/ticketsauce/ticketsauce.app.mjs | head -200

Length of output: 1581


🏁 Script executed:

#!/bin/bash
# Search broadly for pagination patterns in prop definitions
rg -B 3 -A 20 "async options.*partnerId.*organizationId" components/ --type mjs | head -100

Length of output: 27


🏁 Script executed:

#!/bin/bash
# Check if the Ticketsauce API endpoint documentation is mentioned anywhere
rg -i "event.*list|list.*event" components/ticketsauce/ --type md --type mjs | grep -i "per_page\|page\|limit\|offset"

Length of output: 27


🏁 Script executed:

#!/bin/bash
# Get just the file with line numbers to see exact structure
cat -n components/ticketsauce/ticketsauce.app.mjs | head -180

Length of output: 3981


🏁 Script executed:

#!/bin/bash
# Check all files in ticketsauce directory
ls -la components/ticketsauce/

Length of output: 379


🏁 Script executed:

#!/bin/bash
# Get comprehensive view of the app.mjs file
head -300 components/ticketsauce/ticketsauce.app.mjs | tail -150

Length of output: 3029


🏁 Script executed:

#!/bin/bash
# Search for the actual line numbers mentioned (7-30 and 31-71)
sed -n '1,80p' components/ticketsauce/ticketsauce.app.mjs | cat -n

Length of output: 2463


🏁 Script executed:

#!/bin/bash
# Final attempt to get the complete structure to understand pagination
python3 << 'EOF'
import json
try:
    with open('components/ticketsauce/ticketsauce.app.mjs', 'r') as f:
        content = f.read()
    # Print first 1000 characters with line numbers
    for i, line in enumerate(content.split('\n')[:120], 1):
        print(f"{i:3d}: {line}")
except Exception as e:
    print(f"Error: {e}")
EOF

Length of output: 3304


🏁 Script executed:

#!/bin/bash
# Look at the entire component to understand its structure
wc -l components/ticketsauce/ticketsauce.app.mjs
cat components/ticketsauce/ticketsauce.app.mjs | head -250

Length of output: 3076


🏁 Script executed:

#!/bin/bash
# Search for pagination in this specific component more thoroughly
rg "page|pagination|per_page|prevContext|offset|limit" components/ticketsauce/ -A 2 -B 2

Length of output: 10360


🏁 Script executed:

#!/bin/bash
# Check if the component has actions or methods that show how the API works
find components/ticketsauce -type f -name "*.mjs" -o -name "*.js" | xargs ls -la

Length of output: 882


🏁 Script executed:

#!/bin/bash
# Look at test files or examples if they exist
find components/ticketsauce -name "*test*" -o -name "*example*" -o -name "*action*" | xargs cat 2>/dev/null | head -200

Length of output: 1485


🏁 Script executed:

#!/bin/bash
# Get the actual entire file now
cat components/ticketsauce/ticketsauce.app.mjs

Length of output: 3029


🏁 Script executed:

#!/bin/bash
# Simple check: does the file exist and get its size
stat components/ticketsauce/ticketsauce.app.mjs 2>&1 && echo "---" && wc -l components/ticketsauce/ticketsauce.app.mjs

Length of output: 42


🏁 Script executed:

#!/bin/bash
# Use python to read and display the file safely
python3 -c "
with open('components/ticketsauce/ticketsauce.app.mjs', 'r') as f:
    lines = f.readlines()
    for i, line in enumerate(lines[:200], 1):
        print(f'{i:4d}: {line}', end='')
"

Length of output: 3845


🏁 Script executed:

#!/bin/bash
# Double-check the component exists and examine its key sections
file components/ticketsauce/ticketsauce.app.mjs && echo "---FILE EXISTS---" && head -250 components/ticketsauce/ticketsauce.app.mjs

Length of output: 42


🏁 Script executed:

#!/bin/bash
# If the direct approach fails, try finding similar components with working pagination
find components -name "*.app.mjs" -type f | xargs grep -l "prevContext" | head -5 | xargs -I {} sh -c 'echo "=== {} ===" && grep -A 30 "async options" {}'

Length of output: 12766


🏁 Script executed:

#!/bin/bash
# Look at how other components implement pagination to validate the pattern
rg -A 40 "prevContext\?\s*\." components --type mjs | head -150

Length of output: 27


🏁 Script executed:

#!/bin/bash
# Check if orderid exists in the file at all
grep -c "orderId\|eventId" components/ticketsauce/ticketsauce.app.mjs || echo "Pattern not found"

Length of output: 2


🏁 Script executed:

#!/bin/bash
# Final comprehensive check
python3 << 'EOF'
with open('components/ticketsauce/ticketsauce.app.mjs', 'r') as f:
    content = f.read()
    
# Show file length
print(f"Total lines: {len(content.split(chr(10)))}")
print("\n--- FIRST 300 LINES ---\n")
lines = content.split('\n')
for i, line in enumerate(lines[:300], 1):
    print(f"{i:4}: {line}")
EOF

Length of output: 3895


🏁 Script executed:

#!/bin/bash
# Check Ticketsauce API docs if available in repo
find . -name "*ticketsauce*" -type f | head -20

Length of output: 44


🏁 Script executed:

#!/bin/bash
# Last resort: use head with explicit count
head -n 400 components/ticketsauce/ticketsauce.app.mjs

Length of output: 3029


🏁 Script executed:

#!/bin/bash
# Check all mjs files in the component directory
find components/ticketsauce -name "*.mjs" | xargs wc -l

Length of output: 550


🏁 Script executed:

#!/bin/bash
# Display directory structure
ls -R components/ticketsauce/

Length of output: 649


🏁 Script executed:

#!/bin/bash
# Most direct approach - read the file
cat components/ticketsauce/ticketsauce.app.mjs 2>&1 | head -400

Length of output: 3029


🏁 Script executed:

#!/bin/bash
# Check if orderId or eventId exists and list line numbers
grep -n "orderId\|eventId\|listEvents\|getOrderDetails\|getEventDetails" components/ticketsauce/ticketsauce.app.mjs | head -30

Length of output: 521


🏁 Script executed:

#!/bin/bash
# Get the section between propDefinitions and the methods
awk '/propDefinitions/,/^  [a-zA-Z_].*\(/ {print NR": "$0}' components/ticketsauce/ticketsauce.app.mjs | head -200

Length of output: 3486


🏁 Script executed:

#!/bin/bash
# Simple line extraction
awk 'NR>=1 && NR<=250 {print NR": "$0}' components/ticketsauce/ticketsauce.app.mjs

Length of output: 3601


🏁 Script executed:

#!/bin/bash
# Try to find the propDefinitions section more carefully
sed -n '1,200p' components/ticketsauce/ticketsauce.app.mjs | nl

Length of output: 40


🏁 Script executed:

#!/bin/bash
# Use a Python approach to handle the file robustly
python3 << 'PYTHON'
try:
    with open('components/ticketsauce/ticketsauce.app.mjs') as f:
        for i, line in enumerate(f, 1):
            if i <= 300:
                print(f"{i:4}: {line.rstrip()}")
            else:
                break
except FileNotFoundError:
    print("File not found")
except Exception as e:
    print(f"Error: {e}")
PYTHON

Length of output: 3845


🏁 Script executed:

#!/bin/bash
# Extract propDefinitions section more robustly
python3 << 'PYTHON'
import re
try:
    with open('components/ticketsauce/ticketsauce.app.mjs') as f:
        content = f.read()
    
    # Find propDefinitions
    match = re.search(r'propDefinitions\s*=\s*\{(.*?)\n  \}', content, re.DOTALL)
    if match:
        prop_section = match.group(1)
        lines = prop_section.split('\n')
        for i, line in enumerate(lines[:150], 1):
            print(f"{i:4}: {line}")
    else:
        print("propDefinitions not found. Showing first 300 lines:")
        for i, line in enumerate(content.split('\n')[:300], 1):
            print(f"{i:4}: {line}")
except Exception as e:
    print(f"Error: {e}")
PYTHON

Length of output: 3904


🏁 Script executed:

#!/bin/bash
# Check if there's an orderId property that shows pagination
python3 << 'PYTHON'
import re
try:
    with open('components/ticketsauce/ticketsauce.app.mjs') as f:
        content = f.read()
    
    # Look for both eventId and orderId
    if 'orderId' in content:
        print("orderId FOUND - extracting context:")
        idx = content.find('orderId')
        print(content[max(0, idx-100):min(len(content), idx+500)])
        print("\n---\n")
    
    if 'eventId' in content:
        print("eventId FOUND - extracting context:")
        idx = content.find('eventId')
        print(content[max(0, idx-100):min(len(content), idx+500)])
    
    if 'orderId' not in content and 'eventId' not in content:
        print("Neither orderId nor eventId found. First 500 chars:")
        print(content[:500])
except Exception as e:
    print(f"Error: {e}")
PYTHON

Length of output: 1279


🏁 Script executed:

#!/bin/bash
# Get comprehensive view using tail and head
total=$(wc -l < components/ticketsauce/ticketsauce.app.mjs)
echo "Total lines: $total"
head -n 300 components/ticketsauce/ticketsauce.app.mjs

Length of output: 3046


🏁 Script executed:

#!/bin/bash
# Verify the component file is readable
test -r components/ticketsauce/ticketsauce.app.mjs && echo "File is readable" || echo "File not readable"
ls -la components/ticketsauce/ticketsauce.app.mjs
cat components/ticketsauce/ticketsauce.app.mjs

Length of output: 3138


🏁 Script executed:

#!/bin/bash
# Extract and display the propDefinitions
rg -A 250 "propDefinitions\s*=" components/ticketsauce/ticketsauce.app.mjs | head -300

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Just dump the whole file with line numbers
nl -ba components/ticketsauce/ticketsauce.app.mjs | head -300

Length of output: 40


🏁 Script executed:

#!/bin/bash
# Use sed to extract lines 1-300
sed -n '1,300p' components/ticketsauce/ticketsauce.app.mjs | cat -n

Length of output: 3981


🏁 Script executed:

#!/bin/bash
# Use awk to display with line numbers
awk '{print NR": "$0}' components/ticketsauce/ticketsauce.app.mjs | head -300

Length of output: 3601


🏁 Script executed:

#!/bin/bash
# Try a basic cat with explicit line selection
cat components/ticketsauce/ticketsauce.app.mjs | sed -n '1,300p' | nl

Length of output: 40


🏁 Script executed:

#!/bin/bash
# Ultimate fallback - use less then pipe through sed
head -300 < components/ticketsauce/ticketsauce.app.mjs | nl -ba -v 1

Length of output: 40


🏁 Script executed:

#!/bin/bash
# Read using python line by line
python3 << 'PYEOF'
with open('components/ticketsauce/ticketsauce.app.mjs', 'r', encoding='utf-8', errors='ignore') as f:
    for line_num, line in enumerate(f, 1):
        if line_num <= 300:
            print(f"{line_num:4d}| {line}", end='')
PYEOF

Length of output: 3845


🏁 Script executed:

#!/bin/bash
# Check the actual structure by looking at the propDefinitions key
grep -n "propDefinitions" components/ticketsauce/ticketsauce.app.mjs && sed -n '1,150p' components/ticketsauce/ticketsauce.app.mjs

Length of output: 3052


🏁 Script executed:

#!/bin/bash
# Look at both patterns in the review - orderId and eventId
rg "orderId|eventId" components/ticketsauce/ticketsauce.app.mjs -B 5 -A 15

Length of output: 1769


🏁 Script executed:

#!/bin/bash
# Extract the exact lines mentioned in the review (7-30 and 31-71)
echo "=== Lines 1-80 of ticketsauce.app.mjs ===" && sed -n '1,80p' components/ticketsauce/ticketsauce.app.mjs && echo "" && echo "=== Line count ===" && wc -l components/ticketsauce/ticketsauce.app.mjs

Length of output: 2012


🏁 Script executed:

#!/bin/bash
# Final attempt: read entire file and pipe through tools
cat components/ticketsauce/ticketsauce.app.mjs | head -150

Length of output: 3029


🏁 Script executed:

#!/bin/bash
# Check if code is readable and get a meaningful snippet
file components/ticketsauce/ticketsauce.app.mjs && head -c 2000 components/ticketsauce/ticketsauce.app.mjs

Length of output: 42


🏁 Script executed:

#!/bin/bash
# Try expanding the view
expand components/ticketsauce/ticketsauce.app.mjs | head -300

Length of output: 44


🏁 Script executed:

#!/bin/bash
# Most basic approach that should work
strings components/ticketsauce/ticketsauce.app.mjs | head -300

Length of output: 45


🏁 Script executed:

#!/bin/bash
# Try with iconv if encoding issues
iconv -f UTF-8 -t UTF-8 components/ticketsauce/ticketsauce.app.mjs 2>/dev/null | head -250 || cat components/ticketsauce/ticketsauce.app.mjs | head -250

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Last resort: use od or hexdump to check file integrity then cat
od -c components/ticketsauce/ticketsauce.app.mjs | head -20 && echo "---" && cat components/ticketsauce/ticketsauce.app.mjs | head -200

Length of output: 3074


🏁 Script executed:

#!/bin/bash
# Simplest possible: just read it
cat < components/ticketsauce/ticketsauce.app.mjs | head -n 200

Length of output: 3029


🏁 Script executed:

#!/bin/bash
# Check file permissions and try reading
stat components/ticketsauce/ticketsauce.app.mjs
timeout 5 cat components/ticketsauce/ticketsauce.app.mjs | head -n 250

Length of output: 88


🏁 Script executed:

#!/bin/bash
# Read the full file into a variable and extract
content=$(cat components/ticketsauce/ticketsauce.app.mjs 2>&1)
echo "$content" | head -200

Length of output: 3029


🏁 Script executed:

#!/bin/bash
# Use find to verify the file and then read it
find . -path "*ticketsauce/ticketsauce.app.mjs" -exec head -200 {} \;

Length of output: 3029


🏁 Script executed:

#!/bin/bash
# Final comprehensive script
ls -la components/ticketsauce/
echo "---"
echo "File type:"
file components/ticketsauce/ticketsauce.app.mjs
echo "---"
echo "Content:"
cat components/ticketsauce/ticketsauce.app.mjs 2>&1 | head -150

Length of output: 3480


🏁 Script executed:

#!/bin/bash
# Verify the ticketsauce component exists and show its structure
if [ -f components/ticketsauce/ticketsauce.app.mjs ]; then
  echo "✓ File exists"
  head -100 components/ticketsauce/ticketsauce.app.mjs
else
  echo "✗ File not found. Checking directory..."
  find . -name "*ticketsauce*" -type d
  find . -name "*ticketsauce*" -type f | head -10
fi

Length of output: 2291


🏁 Script executed:

#!/bin/bash
# Use process substitution to ensure we can read the file
{ head -250 components/ticketsauce/ticketsauce.app.mjs; } 2>&1

Length of output: 3029


🏁 Script executed:

#!/bin/bash
# Check if the component exists in a different location
find components -name "ticketsauce*" -type f

Length of output: 42


🏁 Script executed:

#!/bin/bash
# Use sed to reliably extract content
sed '1,250!d' components/ticketsauce/ticketsauce.app.mjs

Length of output: 51


🏁 Script executed:

#!/bin/bash
# Double check the file with multiple approaches
test -e components/ticketsauce/ticketsauce.app.mjs && head -n 250 components/ticketsauce/ticketsauce.app.mjs || echo "File search:" && find . -name "ticketsauce.app.mjs"

Length of output: 3074


🏁 Script executed:

#!/bin/bash
# Most reliable: use bash read builtin
while IFS= read -r line; do
  ((n++))
  [ $n -le 250 ] && echo "$n: $line"
done < components/ticketsauce/ticketsauce.app.mjs

Length of output: 3601


🏁 Script executed:

#!/bin/bash
# Alternative: use awk with BEGIN to show structure
awk 'BEGIN{n=0} {n++; if(n<=250) print n": "$0}' components/ticketsauce/ticketsauce.app.mjs

Length of output: 3601


🏁 Script executed:

#!/bin/bash
# Final final attempt
(head -n 250 components/ticketsauce/ticketsauce.app.mjs) 2>&1 || (ls components/ticketsauce/ && echo "---" && file components/ticketsauce/ticketsauce.app.mjs)

Length of output: 3029


🏁 Script executed:

#!/bin/bash
# Read file and extract key sections
python3 << 'EOF'
import os
path = 'components/ticketsauce/ticketsauce.app.mjs'
if os.path.exists(path):
    with open(path, 'r', encoding='utf-8', errors='replace') as f:
        lines = f.readlines()
    print(f"Total lines: {len(lines)}\n")
    for i, line in enumerate(lines[:250], 1):
        print(f"{i:4}: {line.rstrip()}")
else:
    print(f"File not found: {path}")
    print("Available files:")
    for root, dirs, files in os.walk('components/ticketsauce'):
        for file in files:
            print(f"  {os.path.join(root, file)}")
EOF

Length of output: 3863


Implement pagination for eventId propDefinition.

eventId.options currently calls listEvents without pagination — users with many events will get truncated results. Apply the same prevContext / per_page / page pattern used by orderId (eventId: components/ticketsauce/ticketsauce.app.mjs, lines 7–30; listEvents: lines 86–105).

      async options({
-        partnerId, organizationId,
+        partnerId, organizationId, prevContext,
      }) {
        const events = await this.listEvents({
          partnerId,
          organizationId,
+          params: {
+            per_page: 100,
+            page: prevContext?.page || 0,
+          },
        });

        if (!events?.length) {
-          return [];
+          return prevContext?.page > 0
+            ? {
+              options: [],
+              context: {},
+            }
+            : [];
        }

        const options = events.map((eventData) => ({
          label: `${eventData.Event.name} - ${eventData.Event.city} (${eventData.Event.start})`,
          value: eventData.Event.id,
        }));

-        return options;
+        return {
+          options,
+          context: {
+            page: (prevContext?.page || 0) + 1,
+          },
+        };
      },

Verify /events accepts per_page/page (other ticketsauce actions use per_page/page for orders/tickets).

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
eventId: {
type: "string",
label: "Event",
description: "Select an event",
async options({
partnerId, organizationId,
}) {
const events = await this.listEvents({
partnerId,
organizationId,
});
if (!events?.length) {
return [];
}
const options = events.map((eventData) => ({
label: `${eventData.Event.name} - ${eventData.Event.city} (${eventData.Event.start})`,
value: eventData.Event.id,
}));
return options;
},
},
eventId: {
type: "string",
label: "Event",
description: "Select an event",
async options({
partnerId, organizationId, prevContext,
}) {
const events = await this.listEvents({
partnerId,
organizationId,
params: {
per_page: 100,
page: prevContext?.page || 0,
},
});
if (!events?.length) {
return prevContext?.page > 0
? {
options: [],
context: {},
}
: [];
}
const options = events.map((eventData) => ({
label: `${eventData.Event.name} - ${eventData.Event.city} (${eventData.Event.start})`,
value: eventData.Event.id,
}));
return {
options,
context: {
page: (prevContext?.page || 0) + 1,
},
};
},
},

Copy link
Collaborator Author

@sergio-eliot-rodriguez sergio-eliot-rodriguez Oct 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pagination is not supported. "List of Events" endpoint returns all events, users always can filter out data.

List of Events
GET /v2/events
Get a list of all events you own. This data is not only sortable, but can be filtered by a large number of optional parameters. All date/time options should be UTC.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sergio-eliot-rodriguez, thank you for clarifying! If the /events endpoint returns all events without pagination support, then the current implementation is correct. I appreciate you sharing this API behavior detail.


✏️ Learnings added
Learnt from: sergio-eliot-rodriguez
PR: PipedreamHQ/pipedream#18787
File: components/ticketsauce/ticketsauce.app.mjs:7-30
Timestamp: 2025-10-17T06:58:24.566Z
Learning: The TicketSauce "List of Events" API endpoint (GET /v2/events) does not support pagination and returns all events. Users can filter the data using the available query parameters (partner_id, organization_id, etc.) rather than paginating through results.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

@sergio-eliot-rodriguez
Copy link
Collaborator Author

Resolves #18366

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
components/ticketsauce/actions/get-orders/get-orders.mjs (2)

153-157: Add an action run summary.

Set a concise $summary so users see a helpful message in the UI.

-    return this.ticketsauce.listOrders({
+    const res = await this.ticketsauce.listOrders({
       eventId: this.eventId,
       params,
     });
+    this.$summary = `Retrieved orders for event ${this.eventId}`;
+    return res;

38-51: Use integer types, enforce bounds, and exclude undefined params.

The Ticketsauce app helper passes params directly to axios without sanitization or type conversion. Verify the refactor against the Ticketsauce API documentation to confirm the Max 500 per_page limit, then apply these changes:

@@
     perPage: {
-      type: "string",
+      type: "integer",
       label: "Per Page",
       description: "How many results to retrieve (per page). Max 500.",
       optional: true,
-      default: "100",
+      default: 100,
+      min: 1,
+      max: 500,
     },
     page: {
-      type: "string",
+      type: "integer",
       label: "Page",
       description: "Which page to return. For example, if per_page is 20, and page is 3, the results would show 41-60.",
       optional: true,
-      default: "1",
+      default: 1,
+      min: 1,
     },
@@
-    totalAbove: {
-      type: "string",
+    totalAbove: {
+      type: "integer",
       label: "Total Above",
       description: "Return only orders whose order total is greater than this value.",
       optional: true,
     },
     totalBelow: {
-      type: "string",
+      type: "integer",
       label: "Total Below",
       description: "Return only orders whose order total is less than this value.",
       optional: true,
     },
@@
   async run() {
-    const params = {
-      per_page: this.perPage,
-      page: this.page,
-      q: this.q,
-      return_questionnaires: this.returnQuestionnaires,
-      return_tickets: this.returnTickets,
-      return_line_item_fees: this.returnLineItemFees,
-      ordered_after: this.orderedAfter,
-      ordered_before: this.orderedBefore,
-      modified_after: this.modifiedAfter,
-      modified_before: this.modifiedBefore,
-      sort_by: this.sortBy,
-      sort_dir: this.sortDir,
-      total_above: this.totalAbove,
-      total_below: this.totalBelow,
-    };
+    const perPage = Math.min(Number(this.perPage ?? 100), 500);
+    const page = Math.max(Number(this.page ?? 1), 1);
+    const params = {
+      per_page: perPage,
+      page,
+      ...(this.q && { q: this.q }),
+      ...(this.returnQuestionnaires !== undefined && { return_questionnaires: this.returnQuestionnaires }),
+      ...(this.returnTickets !== undefined && { return_tickets: this.returnTickets }),
+      ...(this.returnLineItemFees !== undefined && { return_line_item_fees: this.returnLineItemFees }),
+      ...(this.orderedAfter && { ordered_after: this.orderedAfter }),
+      ...(this.orderedBefore && { ordered_before: this.orderedBefore }),
+      ...(this.modifiedAfter && { modified_after: this.modifiedAfter }),
+      ...(this.modifiedBefore && { modified_before: this.modifiedBefore }),
+      ...(this.sortBy && { sort_by: this.sortBy }),
+      ...(this.sortDir && { sort_dir: this.sortDir }),
+      ...(this.totalAbove !== undefined && { total_above: this.totalAbove }),
+      ...(this.totalBelow !== undefined && { total_below: this.totalBelow }),
+    };

Also applies to: lines 122-133, 135-151

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 46e2542 and 3418247.

📒 Files selected for processing (1)
  • components/ticketsauce/actions/get-orders/get-orders.mjs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
components/ticketsauce/actions/get-orders/get-orders.mjs (3)
components/ticketsauce/actions/get-ticket-checkin-ids/get-ticket-checkin-ids.mjs (1)
  • params (53-56)
components/ticketsauce/actions/get-events/get-events.mjs (1)
  • params (88-98)
components/ticketsauce/actions/get-event-details/get-event-details.mjs (1)
  • params (58-61)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: pnpm publish
  • GitHub Check: Lint Code Base
  • GitHub Check: Verify TypeScript components
  • GitHub Check: Publish TypeScript components
🔇 Additional comments (1)
components/ticketsauce/actions/get-orders/get-orders.mjs (1)

28-37: Dynamic event selector looks good.

Clean use of propDefinition with partnerId/organizationId context to scope event options.

export default {
key: "ticketsauce-get-orders",
name: "Get Orders",
description: "Get a list of orders from the specified event. [See documentation](https://speca.io/ticketsauce/ticketsauce-public-api?key=204000d6bda66da78315e721920f43aa#orders)",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Use a stable docs URL (avoid query keys in the link).

The speca URL includes a ?key=... parameter that may be temporary. Link to the canonical page to prevent future link rot.


🌐 Web query:

What is the canonical public documentation URL for the Ticketsauce Orders endpoint (without a temporary key parameter)?

💡 Result:

Do you mean the TicketSauce API "Orders" documentation page (their public API docs)? If so, please confirm — I couldn't find a clear canonical Orders-docs URL and will search again once you confirm.


I'll perform a more targeted search to find Ticketsauce's official API documentation structure.

Let me search more specifically for Ticketsauce's official developer documentation.

Let me search specifically for information about speca.io and its URL structure.

Update the URL to remove the temporary query parameter.

The ?key=... parameter is not part of standard Speca.io documentation URLs and should be removed. Speca is an API design and documentation platform, and its canonical URL format is https://speca.io/[owner]/[api-name] without query parameters.

Change the link from:

https://speca.io/ticketsauce/ticketsauce-public-api?key=204000d6bda66da78315e721920f43aa#orders

To:

https://speca.io/ticketsauce/ticketsauce-public-api#orders
🤖 Prompt for AI Agents
components/ticketsauce/actions/get-orders/get-orders.mjs around line 6: the
documentation URL in the description includes a temporary query parameter
(?key=...) which should be removed; update the link to
https://speca.io/ticketsauce/ticketsauce-public-api#orders so it follows the
canonical speca.io format without the query string and retains the #orders
fragment.

Copy link
Collaborator

@GTFalcao GTFalcao left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made a few comments, some of which may apply to more files. Please check them and let me know if anything is needed.

@GTFalcao GTFalcao moved this from Ready for PR Review to Changes Required in Component (Source and Action) Backlog Oct 17, 2025
sergio-eliot-rodriguez and others added 12 commits October 17, 2025 22:35
…nents

Pulling changes commited by Guilherme during his revie
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Enhanced prop descriptions: added markdown in date formats, corrected English spelling, etc.

Co-authored-by: Guilherme Falcão <[email protected]>
Enhanced prop descriptions: added markdown in date formats, corrected English spelling, etc.

Co-authored-by: Guilherme Falcão <[email protected]>
…ails.mjs


Enhanced prop descriptions: added markdown in date formats, corrected English spelling, etc.

Co-authored-by: Guilherme Falcão <[email protected]>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Enhanced prop descriptions: added markdown in date formats, corrected English spelling, etc.

Co-authored-by: Guilherme Falcão <[email protected]>
Enhanced prop descriptions: added markdown in date formats, corrected English spelling, etc.

Co-authored-by: Guilherme Falcão <[email protected]>
…ails.mjs


Enhanced prop descriptions: added markdown in date formats, corrected English spelling, etc.

Co-authored-by: Guilherme Falcão <[email protected]>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1d1cee5 and 92856bc.

📒 Files selected for processing (7)
  • components/ticketsauce/actions/get-event-details/get-event-details.mjs (1 hunks)
  • components/ticketsauce/actions/get-events/get-events.mjs (1 hunks)
  • components/ticketsauce/actions/get-order-details/get-order-details.mjs (1 hunks)
  • components/ticketsauce/actions/get-orders/get-orders.mjs (1 hunks)
  • components/ticketsauce/actions/get-ticket-checkin-ids/get-ticket-checkin-ids.mjs (1 hunks)
  • components/ticketsauce/sources/new-event/new-event.mjs (1 hunks)
  • components/ticketsauce/ticketsauce.app.mjs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • components/ticketsauce/actions/get-events/get-events.mjs
  • components/ticketsauce/actions/get-ticket-checkin-ids/get-ticket-checkin-ids.mjs
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-10-17T06:58:24.566Z
Learnt from: sergio-eliot-rodriguez
PR: PipedreamHQ/pipedream#18787
File: components/ticketsauce/ticketsauce.app.mjs:7-30
Timestamp: 2025-10-17T06:58:24.566Z
Learning: The TicketSauce "List of Events" API endpoint (GET /v2/events) does not support pagination and returns all events. Users can filter the data using the available query parameters (partner_id, organization_id, etc.) rather than paginating through results.

Applied to files:

  • components/ticketsauce/ticketsauce.app.mjs
🧬 Code graph analysis (4)
components/ticketsauce/sources/new-event/new-event.mjs (1)
components/ticketsauce/ticketsauce.app.mjs (1)
  • events (37-40)
components/ticketsauce/actions/get-event-details/get-event-details.mjs (1)
components/ticketsauce/actions/get-events/get-events.mjs (1)
  • params (116-126)
components/ticketsauce/ticketsauce.app.mjs (5)
components/ticketsauce/sources/new-event/new-event.mjs (1)
  • events (57-65)
components/ticketsauce/actions/get-event-details/get-event-details.mjs (1)
  • params (57-60)
components/ticketsauce/actions/get-events/get-events.mjs (1)
  • params (116-126)
components/ticketsauce/actions/get-orders/get-orders.mjs (1)
  • params (163-178)
components/ticketsauce/actions/get-ticket-checkin-ids/get-ticket-checkin-ids.mjs (1)
  • params (53-56)
components/ticketsauce/actions/get-orders/get-orders.mjs (3)
components/ticketsauce/actions/get-event-details/get-event-details.mjs (1)
  • params (57-60)
components/ticketsauce/actions/get-events/get-events.mjs (1)
  • params (116-126)
components/ticketsauce/actions/get-ticket-checkin-ids/get-ticket-checkin-ids.mjs (1)
  • params (53-56)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: pnpm publish
  • GitHub Check: Lint Code Base
  • GitHub Check: Verify TypeScript components
  • GitHub Check: Publish TypeScript components
🔇 Additional comments (4)
components/ticketsauce/actions/get-order-details/get-order-details.mjs (1)

1-53: LGTM!

The action is well-structured and follows Pipedream component guidelines. It properly uses propDefinitions, chains dependencies correctly (orderId → eventId → partnerId/organizationId), and delegates to the Ticketsauce client.

components/ticketsauce/actions/get-event-details/get-event-details.mjs (1)

1-67: LGTM!

The action properly implements boolean conversions for the photos and includePerformers parameters, consistent with the pattern used in get-events.mjs. The propDefinition usage and API delegation are correct.

components/ticketsauce/ticketsauce.app.mjs (1)

1-164: LGTM!

The app file is well-structured with proper propDefinitions and API methods. The implementation correctly handles:

  • Pagination for orderId (orders support pagination)
  • No pagination for eventId (per learning: List of Events endpoint returns all results)
  • Consistent API method patterns with proper $ parameter passing
  • Proper OAuth token handling in _makeRequest

Based on learnings

components/ticketsauce/actions/get-orders/get-orders.mjs (1)

162-185: LGTM!

The run() method correctly constructs the params object with appropriate type conversions. Boolean flags (returnQuestionnaires, returnTickets, returnLineItemFees) are properly converted using parseInt() === 1, consistent with the pattern used in get-events.mjs and get-event-details.mjs.

@sergio-eliot-rodriguez sergio-eliot-rodriguez moved this from Changes Required to Ready for PR Review in Component (Source and Action) Backlog Oct 21, 2025
Copy link
Collaborator

@jcortes jcortes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @sergio-eliot-rodriguez lgtm! I've just added a suggestion. Ready for QA!

@jcortes jcortes moved this from Ready for PR Review to Ready for QA in Component (Source and Action) Backlog Oct 21, 2025
EwanTauran and others added 4 commits October 21, 2025 15:21
* Add Airweave app with 7 actions for semantic search and collection management.

- Search Collection: semantic + keyword search across data sources
- List/Create/Get/Delete Collections
- List Available Sources
- Trigger Source Connection Sync

Includes full @airweave/sdk integration, dynamic dropdowns, and comprehensive documentation.

* Running ESLint and PNPM, adding annotations

* Integrate AirweaveSDKClient with framework details

- Added frameworkName and frameworkVersion properties to the AirweaveSDKClient instantiation.
- Imported package.json to dynamically set the framework version.

* Update airweave.app.mjs

---------

Co-authored-by: Guilherme Falcão <[email protected]>
Co-authored-by: GTFalcao <[email protected]>
…iot-rodriguez/sergio_wong_does_pipedream into ticketsauce-components

syncing upstream with my fork addressing ticketsauce components
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 15

♻️ Duplicate comments (1)
components/microsoft_teams/sources/new-channel/new-channel.mjs (1)

8-8: Same concern as new-team-member: verify version bump necessity.

This file also shows only a version bump (0.0.12 → 0.0.13) with no functional changes, and appears unrelated to the TicketSauce-focused PR objectives.

See the review comment on components/microsoft_teams/sources/new-team-member/new-team-member.mjs for verification steps.

🧹 Nitpick comments (9)
components/ticketsauce/actions/get-event-details/get-event-details.mjs (1)

38-48: Consider using a boolean prop type for better UX.

The past review suggested using type: "boolean" for this prop. Since the API accepts boolean values (as seen in line 58), you can simplify both the prop definition and the conversion logic:

Apply this diff:

 photos: {
-  type: "string",
+  type: "boolean",
   label: "Photos",
   description: "Whether or not to return the event's photo gallery records.",
   optional: true,
-  default: "0",
-  options: [
-    "0",
-    "1",
-  ],
+  default: false,
 },

Then simplify line 58:

 const params = {
-  photos: parseInt(this.photos) === 1,
+  photos: this.photos,
   include_performers: parseInt(this.includePerformers) === 1,
 };

This provides a better user experience (toggle instead of dropdown) and removes unnecessary conversion logic. The same refactor could apply to includePerformers if its propDefinition follows a similar pattern.

components/airweave/actions/create-collection/create-collection.mjs (1)

16-31: Add lightweight input sanitization/validation for readableId.

Fail fast and avoid an API 4xx by trimming and validating the slug shape before calling the SDK. Also trim name/description for ergonomics.

   async run({ $ }) {
-    const response = await this.airweave.createCollection({
-      name: this.name,
-      readable_id: this.readableId,
-      description: this.description,
-    });
+    const name = this.name?.trim();
+    const readable_id = this.readableId?.trim();
+    const description = this.description?.trim();
+    if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(readable_id)) {
+      throw new Error("Readable ID must be lowercase alphanumeric words separated by single hyphens, e.g. 'customer-support-data'.");
+    }
+    const response = await this.airweave.createCollection({
+      name,
+      readable_id,
+      description,
+    });

As per component guidelines.

Also applies to: 33-38

components/airweave/package.json (1)

3-3: Package hygiene: consider adding license/repository/engines/files.

Not required, but improves publishability and tooling.

   "author": "Pipedream <[email protected]> (https://pipedream.com/)",
+  "license": "MIT",
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/PipedreamHQ/pipedream"
+  },
+  "engines": {
+    "node": ">=18"
+  },
+  "files": [
+    "airweave.app.mjs",
+    "actions/",
+    "sources/"
+  ],
   "publishConfig": {
     "access": "public"
   }

Also applies to: 15-18

components/airweave/actions/list-sources/list-sources.mjs (1)

18-23: Defensive count in case the SDK returns a non-array shape.

Small guard avoids response.length throwing if the SDK wraps results.

-    const count = response.length;
-    $.export("$summary", `Successfully retrieved ${count} available source connector(s)`);
+    const count = Array.isArray(response)
+      ? response.length
+      : (Array.isArray(response?.data) ? response.data.length : 0);
+    $.export("$summary", `Successfully retrieved ${count} available source connector(s)`);
components/airweave/actions/list-collections/list-collections.mjs (1)

14-33: Support “fetch all pages” to meet pagination guideline.

Add a boolean to auto-paginate; fall back to single page when false. Keeps defaults intact.

   props: {
     airweave,
+    fetchAll: {
+      type: "boolean",
+      label: "Fetch all pages",
+      description: "If enabled, retrieves all collections by following pagination.",
+      optional: true,
+      default: false,
+    },
     skip: {
@@
   async run({ $ }) {
-    const response = await this.airweave.listCollections({
-      skip: this.skip,
-      limit: this.limit,
-    });
+    const doFetchAll = !!this.fetchAll;
+    let response = [];
+    if (doFetchAll) {
+      let skip = this.skip ?? 0;
+      const limit = this.limit ?? 50;
+      // Defensive loop with cap
+      for (let i = 0; i < 200; i++) {
+        const page = await this.airweave.listCollections({ skip, limit });
+        const items = Array.isArray(page) ? page : (page?.results || []);
+        response.push(...items);
+        if (items.length < limit) break;
+        skip += items.length;
+      }
+    } else {
+      const page = await this.airweave.listCollections({ skip: this.skip, limit: this.limit });
+      response = Array.isArray(page) ? page : (page?.results || []);
+    }
 
-    const count = response.length;
+    const count = response.length;
     $.export("$summary", `Successfully retrieved ${count} collection(s)`);
 
     return response;
   },

Confirm listCollections returns an array vs an object with results/next cursor. If the SDK exposes total/next, we can switch to that for precision.

Also applies to: 34-44

components/airweave/actions/search-collection/search-collection.mjs (1)

75-79: Adjust summary for completion vs results.

When responseType is “completion”, results may be empty; tailor the summary accordingly.

-    const resultCount = response.results?.length || 0;
-    $.export("$summary", `Successfully searched collection "${this.collectionId}" and found ${resultCount} result(s)`);
+    const mode = this.responseType || "results";
+    if (mode === "completion") {
+      const hasAnswer = !!(response?.completion || response?.answer);
+      $.export("$summary", `Generated completion for collection "${this.collectionId}"${hasAnswer ? "" : " (no answer)"}`);
+    } else {
+      const resultCount = response.results?.length || 0;
+      $.export("$summary", `Searched collection "${this.collectionId}" and found ${resultCount} result(s)`);
+    }
 
     return response;

Please confirm the SDK uses response_type and offset param names (vs format/skip) and completion field name (completion vs answer).

Also applies to: 34-39

components/airweave/airweave.app.mjs (3)

33-53: Same pagination hint for sourceConnectionId options.

Mirror the hasMore/next token approach here, too, to avoid UI calling without a stop condition.

         return {
           options: connections.map((conn) => ({
             label: conn.name || conn.id,
             value: conn.id,
           })),
-          context: {
-            skip: params.skip + connections.length,
-          },
+          context: {
+            skip: params.skip + connections.length,
+            hasMore: connections.length === params.limit,
+          },
         };

93-100: Cache the SDK client to reduce per-call instantiation overhead.

Lightweight but cleaner and cheaper at runtime.

-    _client() {
-      return new AirweaveSDKClient({
-        apiKey: this._apiKey(),
-        baseUrl: this._baseUrl(),
-        frameworkName: "pipedream",
-        frameworkVersion: "0.1.0",
-      });
-    },
+    _client() {
+      if (!this._clientInstance) {
+        this._clientInstance = new AirweaveSDKClient({
+          apiKey: this._apiKey(),
+          baseUrl: this._baseUrl(),
+          frameworkName: "pipedream",
+          frameworkVersion: "0.1.0",
+        });
+      }
+      return this._clientInstance;
+    },

86-100: Optional: expose a test() method for connection validation.

Useful for “Test” button and clearer auth failures.

   methods: {
+    async test() {
+      // Lightweight call to validate credentials and base URL
+      await this.listSources();
+      return { ok: true };
+    },
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 92856bc and 37abd15.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (34)
  • components/airweave/README.md (1 hunks)
  • components/airweave/actions/create-collection/create-collection.mjs (1 hunks)
  • components/airweave/actions/delete-collection/delete-collection.mjs (1 hunks)
  • components/airweave/actions/get-collection/get-collection.mjs (1 hunks)
  • components/airweave/actions/list-collections/list-collections.mjs (1 hunks)
  • components/airweave/actions/list-sources/list-sources.mjs (1 hunks)
  • components/airweave/actions/search-collection/search-collection.mjs (1 hunks)
  • components/airweave/actions/trigger-sync/trigger-sync.mjs (1 hunks)
  • components/airweave/airweave.app.mjs (1 hunks)
  • components/airweave/package.json (1 hunks)
  • components/coinapi/coinapi.app.mjs (1 hunks)
  • components/coinapi/package.json (1 hunks)
  • components/copicake/copicake.app.mjs (1 hunks)
  • components/copicake/package.json (1 hunks)
  • components/cronly/cronly.app.mjs (1 hunks)
  • components/cronly/package.json (1 hunks)
  • components/microsoft_teams/actions/create-channel/create-channel.mjs (1 hunks)
  • components/microsoft_teams/actions/list-channels/list-channels.mjs (1 hunks)
  • components/microsoft_teams/actions/list-shifts/list-shifts.mjs (1 hunks)
  • components/microsoft_teams/actions/send-channel-message/send-channel-message.mjs (1 hunks)
  • components/microsoft_teams/actions/send-chat-message/send-chat-message.mjs (1 hunks)
  • components/microsoft_teams/microsoft_teams.app.mjs (1 hunks)
  • components/microsoft_teams/package.json (1 hunks)
  • components/microsoft_teams/sources/new-channel-message/new-channel-message.mjs (1 hunks)
  • components/microsoft_teams/sources/new-channel/new-channel.mjs (1 hunks)
  • components/microsoft_teams/sources/new-chat-message/new-chat-message.mjs (1 hunks)
  • components/microsoft_teams/sources/new-chat/new-chat.mjs (1 hunks)
  • components/microsoft_teams/sources/new-team-member/new-team-member.mjs (1 hunks)
  • components/microsoft_teams/sources/new-team/new-team.mjs (1 hunks)
  • components/ticketsauce/actions/get-event-details/get-event-details.mjs (1 hunks)
  • components/ticketsauce/actions/get-order-details/get-order-details.mjs (1 hunks)
  • components/ticketsauce/actions/get-ticket-checkin-ids/get-ticket-checkin-ids.mjs (1 hunks)
  • components/topdesk/package.json (1 hunks)
  • components/topdesk/topdesk.app.mjs (1 hunks)
✅ Files skipped from review due to trivial changes (9)
  • components/microsoft_teams/package.json
  • components/microsoft_teams/sources/new-team/new-team.mjs
  • components/microsoft_teams/sources/new-channel-message/new-channel-message.mjs
  • components/microsoft_teams/sources/new-chat-message/new-chat-message.mjs
  • components/airweave/README.md
  • components/microsoft_teams/actions/send-channel-message/send-channel-message.mjs
  • components/microsoft_teams/actions/list-shifts/list-shifts.mjs
  • components/microsoft_teams/actions/create-channel/create-channel.mjs
  • components/microsoft_teams/sources/new-chat/new-chat.mjs
🚧 Files skipped from review as they are similar to previous changes (2)
  • components/ticketsauce/actions/get-order-details/get-order-details.mjs
  • components/ticketsauce/actions/get-ticket-checkin-ids/get-ticket-checkin-ids.mjs
🧰 Additional context used
🧬 Code graph analysis (8)
components/airweave/actions/list-sources/list-sources.mjs (1)
components/airweave/actions/list-collections/list-collections.mjs (2)
  • response (35-38)
  • count (40-40)
components/ticketsauce/actions/get-event-details/get-event-details.mjs (4)
components/ticketsauce/actions/get-ticket-checkin-ids/get-ticket-checkin-ids.mjs (2)
  • params (53-56)
  • response (58-61)
components/ticketsauce/actions/get-events/get-events.mjs (1)
  • params (116-126)
components/ticketsauce/actions/get-orders/get-orders.mjs (1)
  • params (163-178)
components/ticketsauce/actions/get-order-details/get-order-details.mjs (1)
  • response (49-51)
components/airweave/actions/create-collection/create-collection.mjs (6)
components/airweave/actions/delete-collection/delete-collection.mjs (1)
  • response (33-33)
components/airweave/actions/get-collection/get-collection.mjs (1)
  • response (24-24)
components/airweave/actions/list-collections/list-collections.mjs (1)
  • response (35-38)
components/airweave/actions/list-sources/list-sources.mjs (1)
  • response (18-18)
components/airweave/actions/search-collection/search-collection.mjs (1)
  • response (70-73)
components/airweave/actions/trigger-sync/trigger-sync.mjs (1)
  • response (34-36)
components/airweave/actions/search-collection/search-collection.mjs (7)
components/airweave/airweave.app.mjs (2)
  • params (12-15)
  • params (35-38)
components/airweave/actions/create-collection/create-collection.mjs (1)
  • response (34-38)
components/airweave/actions/delete-collection/delete-collection.mjs (1)
  • response (33-33)
components/airweave/actions/get-collection/get-collection.mjs (1)
  • response (24-24)
components/airweave/actions/list-collections/list-collections.mjs (1)
  • response (35-38)
components/airweave/actions/list-sources/list-sources.mjs (1)
  • response (18-18)
components/airweave/actions/trigger-sync/trigger-sync.mjs (1)
  • response (34-36)
components/airweave/actions/delete-collection/delete-collection.mjs (2)
components/airweave/actions/create-collection/create-collection.mjs (1)
  • response (34-38)
components/airweave/actions/get-collection/get-collection.mjs (1)
  • response (24-24)
components/airweave/actions/list-collections/list-collections.mjs (1)
components/airweave/actions/list-sources/list-sources.mjs (2)
  • response (18-18)
  • count (20-20)
components/airweave/actions/get-collection/get-collection.mjs (2)
components/airweave/actions/delete-collection/delete-collection.mjs (1)
  • response (33-33)
components/airweave/actions/search-collection/search-collection.mjs (1)
  • response (70-73)
components/airweave/airweave.app.mjs (1)
components/airweave/actions/search-collection/search-collection.mjs (1)
  • params (56-60)
🪛 GitHub Actions: Pull Request Checks
components/coinapi/coinapi.app.mjs

[error] 11-11: ESLint: Newline required at end of file but not found. (eol-last)

🪛 GitHub Check: Lint Code Base
components/topdesk/package.json

[failure] 15-15:
Newline required at end of file but not found

components/copicake/copicake.app.mjs

[failure] 11-11:
Newline required at end of file but not found

components/cronly/cronly.app.mjs

[failure] 11-11:
Newline required at end of file but not found

components/topdesk/topdesk.app.mjs

[failure] 11-11:
Newline required at end of file but not found

components/copicake/package.json

[failure] 15-15:
Newline required at end of file but not found

components/coinapi/coinapi.app.mjs

[failure] 11-11:
Newline required at end of file but not found

components/cronly/package.json

[failure] 15-15:
Newline required at end of file but not found

components/coinapi/package.json

[failure] 15-15:
Newline required at end of file but not found

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Verify TypeScript components
  • GitHub Check: Publish TypeScript components
  • GitHub Check: pnpm publish
🔇 Additional comments (11)
components/microsoft_teams/actions/list-channels/list-channels.mjs (1)

8-8: LGTM! Version bump is appropriate.

The version increment is clean, and the existing code follows best practices with proper pagination and summary emission.

components/microsoft_teams/sources/new-team-member/new-team-member.mjs (1)

8-8: The review comment is based on incorrect information and should be dismissed.

This PR contains only changes to TicketSauce action components (get-event-details, get-order-details, get-ticket-checkin-ids). There are no modifications to any Microsoft Teams files, including components/microsoft_teams/sources/new-team-member/new-team-member.mjs. The version "0.0.13" shown in that file is the current state, not a change being made in this PR. The review comment appears to reference a different PR or incorrect file context.

Likely an incorrect or invalid review comment.

components/microsoft_teams/microsoft_teams.app.mjs (1)

274-281: Unable to verify endpoint change claim within codebase.

Verification analysis shows:

  • No internal callers to listChannelMessages found (expected for Pipedream app actions that are exposed to workflow users)
  • No references to delta endpoints or previous delta implementation found in the microsoft_teams component
  • Method signature matches other similar list methods with standard /messages paths
  • No test files exist to validate the endpoint or changes

Since this is a Pipedream app integration, the method is a public API action used by external workflow users rather than being called internally. The claimed change from "delta to regular messages" cannot be confirmed through codebase analysis. You should manually verify:

  1. Whether this was a breaking change from a previous version
  2. The impact on existing Pipedream workflows that may depend on this action
  3. Whether delta updates were previously supported and are now removed
components/ticketsauce/actions/get-event-details/get-event-details.mjs (2)

1-13: LGTM! Metadata and structure follow conventions.

The component key, naming, documentation link, and annotations all follow Pipedream best practices. The read-only hints are appropriate for a GET operation.


56-69: LGTM! Run method correctly addresses past feedback.

The method now properly passes $ to the API call and exports a descriptive summary, addressing previous review comments. The overall structure and error handling flow are solid.

components/microsoft_teams/actions/send-chat-message/send-chat-message.mjs (1)

8-8: <!-- [scratchpad_start]
[task review_file_1/1 review_segment_1/1 check_justification_3/3]
Final analysis: version field is IDENTICAL between branches.

[observations]

  • Master branch: version: "0.0.11"
  • Current branch: version: "0.0.11"
  • git diff: empty (no changes to this file)
  • All changed files in PR: no Microsoft Teams files listed
  • File is NOT modified in this PR

[analysis]

  • The original review comment incorrectly assumes a version bump from 0.0.10 to 0.0.11
  • The version is already "0.0.11" in master branch
  • This file has zero changes in this PR
  • The file content shown in review comment context ("version: 0.0.11") is the final state in MASTER, not a change made by this PR
  • Original review was likely based on misleading AI summary or context confusion

[conclusion]

  • Review comment is INCORRECT
  • There is no version bump to review
  • There are no changes to this file in this PR
  • The review is flagging a non-existent issue

[tag]

Likely an incorrect or invalid review comment.

components/airweave/actions/create-collection/create-collection.mjs (1)

40-42: LGTM overall.

Good key/name, clear description with docs link, emits summary, and returns API response.

components/airweave/actions/get-collection/get-collection.mjs (1)

15-29: LGTM.

Clear props, correct client call, and useful summary. No issues spotted.

components/airweave/package.json (1)

15-18: Verify @airweave/sdk 0.1.50 method compatibility before deploying.

The version 0.1.50 exists on NPM and is specified correctly in package.json. However, the implementation calls multiple SDK methods (collections.create, collections.delete, collections.list, sourceConnections operations, and sources.list) that should be confirmed available in 0.1.50. The latest version is 0.6.59, but the caret constraint locks to 0.1.x. Verify this version supports all the methods used in components/airweave/airweave.app.mjs before deployment.

components/airweave/actions/trigger-sync/trigger-sync.mjs (2)

16-22: Note: collectionId not used in run (only for dependent options).

This looks intentional to filter sourceConnectionId options. If not required, mark it optional; if required for UX, leave as-is.


33-41: Guard against duplicate sync jobs on retries: idempotency suggestion is valid, but verify Airweave SDK return format before implementation.

The methods runSourceConnection() and getSourceConnectionJobs() exist in airweave.app.mjs and are properly exposed. However, their actual return formats are not documented in the codebase—they delegate to the external @airweave/[email protected] package. Before implementing the suggested guard:

  1. Confirm getSourceConnectionJobs() returns either an array or an object with a results[] property
  2. Verify the response from runSourceConnection() includes id and status fields
  3. Consult the Airweave SDK documentation for the exact job status values (the guard assumes "queued" and "running")

The proposed guard logic is defensive and will handle both return formats, but the assumptions about response structure depend on external SDK behavior.

Comment on lines +22 to +31
confirmation: {
type: "string",
label: "Confirmation",
description: "Type 'DELETE' to confirm deletion. This action cannot be undone.",
},
},
async run({ $ }) {
if (this.confirmation !== "DELETE") {
throw new Error("Please type 'DELETE' to confirm deletion. This action cannot be undone.");
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Harden confirmation check and summary for 204/empty responses.

DELETE often returns 204. Guard against undefined response and make confirmation user-proof (trim + case-insensitive).

   confirmation: {
     type: "string",
     label: "Confirmation",
     description: "Type 'DELETE' to confirm deletion. This action cannot be undone.",
+    placeholder: "DELETE",
   },
 ...
   async run({ $ }) {
-    if (this.confirmation !== "DELETE") {
+    if ((this.confirmation ?? "").trim().toUpperCase() !== "DELETE") {
       throw new Error("Please type 'DELETE' to confirm deletion. This action cannot be undone.");
     }
 
-    const response = await this.airweave.deleteCollection(this.collectionId);
+    const response = await this.airweave.deleteCollection(this.collectionId);
 
-    $.export("$summary", `Successfully deleted collection: ${response.name} (${response.readable_id})`);
+    const name = response?.name ?? this.collectionId;
+    const rid = response?.readable_id ?? this.collectionId;
+    $.export("$summary", `Successfully deleted collection: ${name} (${rid})`);

As per component guidelines.

Also applies to: 33-37

🤖 Prompt for AI Agents
In components/airweave/actions/delete-collection/delete-collection.mjs around
lines 22-31 (and similarly apply to 33-37), the confirmation check and handling
of DELETE responses need hardening: make the confirmation check robust by
trimming whitespace and comparing case-insensitively (e.g., normalize
this.confirmation before validating against "DELETE"), and guard response
processing to accept 204/no-body results by checking for undefined/null response
or empty body before accessing fields — treat a 204 or missing body as a
successful deletion and set the summary accordingly; update error messages and
summary logic to reflect these cases.

Comment on lines +48 to +53
recencyBias: {
type: "string",
label: "Recency Bias",
description: "How much to weigh recency vs similarity (0-1). 0 = no recency effect; 1 = rank by recency only",
optional: true,
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Validate recencyBias and avoid passing NaN/out-of-range.

parseFloat may yield NaN; also enforce 0–1 bounds to prevent API errors.

-    recencyBias: {
+    recencyBias: {
       type: "string",
       label: "Recency Bias",
       description: "How much to weigh recency vs similarity (0-1). 0 = no recency effect; 1 = rank by recency only",
       optional: true,
     },
@@
-    if (this.recencyBias !== undefined) {
-      params.recency_bias = parseFloat(this.recencyBias);
-    }
+    if (this.recencyBias !== undefined && this.recencyBias !== "") {
+      const rb = parseFloat(this.recencyBias);
+      if (Number.isNaN(rb) || rb < 0 || rb > 1) {
+        throw new Error(`Invalid recencyBias "${this.recencyBias}". Expected a number between 0 and 1.`);
+      }
+      params.recency_bias = rb;
+    }

Also applies to: 66-68

🤖 Prompt for AI Agents
In components/airweave/actions/search-collection/search-collection.mjs around
lines 48-53 (and also apply same fix to lines 66-68), the recencyBias value is
parsed with parseFloat and may become NaN or outside the allowed 0–1 range;
validate and sanitize it by checking the parsed value is a finite number and
then clamp it to the 0–1 interval (or fallback to a safe default like 0 if
invalid) before passing to the API to avoid NaN or out-of-range errors.

Comment on lines +11 to +27
async options({ prevContext }) {
const params = {
skip: prevContext?.skip || 0,
limit: 50,
};
const collections = await this.listCollections(params);
return {
options: collections.map((collection) => ({
label: collection.name || collection.readable_id,
value: collection.readable_id,
})),
context: {
skip: params.skip + collections.length,
},
};
},
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

🧩 Analysis chain

Async options pagination: include an explicit “hasMore” (or nextPageToken) to prevent over-fetching.

Current pattern returns context.skip; depending on Pipedream UI, you may also need hasMore or nextPageToken to indicate continuation.

         return {
           options: collections.map((collection) => ({
             label: collection.name || collection.readable_id,
             value: collection.readable_id,
           })),
-          context: {
-            skip: params.skip + collections.length,
-          },
+          context: {
+            skip: params.skip + collections.length,
+            hasMore: collections.length === params.limit,
+          },
         };

🌐 Web query:

Pipedream component prop async options: what is the recommended pagination return shape? Do options() support { options, context:{...} } with hasMore, or { options, nextPageToken }?

💡 Result:

Use the docs’ async-options pagination shape: return an object with an options array and a context containing nextPageToken — e.g. { options, context: { nextPageToken } }. Simple (non-paginated) async options can just return an array. The docs require prevContext-based pagination to use nextPageToken (not hasMore). [1][2]

Sources:
[1] Pipedream Component API — Async Options (pagination) example.
[2] Pipedream Components Guidelines — Async Options / pagination recommendation.


Async options pagination: use nextPageToken instead of hasMore per Pipedream docs.

Pipedream's async options pagination requires returning an object with an options array and a context containing nextPageToken. The current implementation should track continuation via nextPageToken rather than hasMore.

         return {
           options: collections.map((collection) => ({
             label: collection.name || collection.readable_id,
             value: collection.readable_id,
           })),
-          context: {
-            skip: params.skip + collections.length,
-          },
+          context: {
+            nextPageToken: collections.length === params.limit ? params.skip + collections.length : undefined,
+          },
         };

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In components/airweave/airweave.app.mjs around lines 11–27, the async options
pagination currently returns a context with skip/hasMore; update it to return
nextPageToken per Pipedream docs: compute nextPageToken as the new offset
(params.skip + collections.length) and set it in context when there are more
results, otherwise set nextPageToken to null/undefined to stop pagination; keep
the options array construction the same. Also remove/stop using prevContext.skip
and instead read prevContext.nextPageToken as the incoming offset for subsequent
calls.

Comment on lines +7 to +9
authKeys() {
console.log(Object.keys(this.$auth));
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Remove or replace debug logging in production code.

The authKeys() method uses console.log(), which will output to logs in production environments. This appears to be leftover debug code.

Consider one of these approaches:

  1. Remove the method entirely if it's not needed:
  propDefinitions: {},
-  methods: {
-    // this.$auth contains connected account data
-    authKeys() {
-      console.log(Object.keys(this.$auth));
-    },
-  },
+  methods: {},
  1. Return the keys instead of logging if this method serves a purpose:
-    authKeys() {
-      console.log(Object.keys(this.$auth));
-    },
+    authKeys() {
+      return Object.keys(this.$auth);
+    },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
authKeys() {
console.log(Object.keys(this.$auth));
},
authKeys() {
return Object.keys(this.$auth);
},
🤖 Prompt for AI Agents
In components/coinapi/coinapi.app.mjs around lines 7 to 9, the authKeys() method
contains a console.log call which is debug logging that should not remain in
production; either remove the method entirely if it is unused, or replace the
console.log with a return of Object.keys(this.$auth) so callers can consume the
value (and update any call sites/tests accordingly), ensuring no console.*
statements remain.

Comment on lines +7 to +9
authKeys() {
console.log(Object.keys(this.$auth));
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Remove or replace debug logging in production code.

The authKeys() method uses console.log(), which will output to logs in production environments. This appears to be leftover debug code.

Consider one of these approaches:

  1. Remove the method entirely if it's not needed:
  propDefinitions: {},
-  methods: {
-    // this.$auth contains connected account data
-    authKeys() {
-      console.log(Object.keys(this.$auth));
-    },
-  },
+  methods: {},
  1. Return the keys instead of logging if this method serves a purpose:
-    authKeys() {
-      console.log(Object.keys(this.$auth));
-    },
+    authKeys() {
+      return Object.keys(this.$auth);
+    },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
authKeys() {
console.log(Object.keys(this.$auth));
},
authKeys() {
return Object.keys(this.$auth);
},
🤖 Prompt for AI Agents
In components/topdesk/topdesk.app.mjs around lines 7 to 9, the authKeys() method
currently calls console.log(Object.keys(this.$auth)); which is debug logging
left in production; either remove the authKeys() method entirely if unused, or
change it to return Object.keys(this.$auth) (or otherwise expose the keys via a
non-logging API) and remove the console.log so no debug output is emitted in
production.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Development

Successfully merging this pull request may close these issues.

7 participants